/**
 * JAVACC DEMO 1.0
 * @copy right dwusoft company All rights reserved. 
 * @Package com.apache.passport.service.plugins  
 */
package com.apache.passport.service.plugins;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.apache.api.manager.PluginConnector;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.database.constant.SystemTools;
import com.apache.database.constant.Validator;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.passport.common.DesUtils;
import com.apache.passport.common.LoginCacheErrTimer;
import com.apache.passport.common.PassportHelper;
import com.apache.passport.entity.BlackRoster;
import com.apache.passport.entity.LoginInfo;
import com.apache.passport.entity.LonErrToken;
import com.apache.passport.entity.Token;
import com.apache.passport.entity.UctUser;
import com.apache.passport.manager.UctUserManager;

/**
 * description:  外部系统登录(socket形式,webservice)
 * 				 此种方式只返回token,下次手机端放的时候,都需要写到token进行传输
 * 				 例如,手机客户端,c#界面登录,以及其他语言的登录,全部使用这种形式或webservice
 * 
 *              2015年5月5日11:07:28  外部系统登录时,添加账户锁定及删除校验
 * @author Hou Dayu 创建时间：2014-12-25  
 * @Copyright(c)2014:
 */
public class OutSideSysLoginPlugin implements PluginConnector {

	protected IDao blackRosterDao;
	protected IDao uctUserDao;
	private UctUserManager uctUserManager;
	private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

	public void setUctUserDao(IDao uctUserDao) {
		this.uctUserDao = uctUserDao;
	}

	public void setUctUserManager(UctUserManager uctUserManager) {
		this.uctUserManager = uctUserManager;
	}

	/**
	 * TODO 例如手机客户端,C# 等语言的登录
	 * 下次手机端放的时候,都需要写到token进行传输
	 * @see com.apache.api.manager.PluginConnector#execute(com.apache.api.vo.ParamsVo)  
	 */
	@Override
	public Object execute(ParamsVo vo) throws Exception {
		String addressIP = String.valueOf(vo.getParams("addressIP"));
		ResultEntity result = new ResultEntity();
		result.setResult("true");

		String userEname = (String) vo.getParams("userEname");
		if (Validator.isEmpty(userEname)) {
			result.setEntity("F");
			result.setMessage("用户名不能为空");
			return result;
		}
		String upass = (String) vo.getParams("userPass");
		if (Validator.isEmpty(upass)) {
			result.setEntity("F");
			result.setMessage("密码不能为空");
			return result;
		}
		ParamsVo<UctUser> vos = new ParamsVo<UctUser>();
		vos = vo;
		//登录前首先从数据库中查询下该用户是否存在于黑名单中
		BlackRoster br = (BlackRoster) getBrInfoByIp(vo);
		if (!Validator.isEmpty(br)) {
			LonErrToken token = new LonErrToken();
			token.setLoginCount("12");
			token.setLoginTime(br.getBrCreatetime());
			//2015年1月29日13:04:07 将用户名添加到错误token中
			token.setUserEname(vos.getObj().getUserEname());
			token.setCacheId(addressIP + br.getBrAccount());
			//存储缓存
			SystemTools.getInstance().getCache("loginErrToken").createCacheObject(addressIP + br.getBrAccount(), token);
			result.setEntity("F");
			result.setMessage("账户已被锁定");
			return result;
		}
		UctUser obj = (UctUser) getInfoByEname(userEname);
		if (!Validator.isEmpty(obj)) {
			//判断密码是否正确
			if ((obj.getUserPass()).equalsIgnoreCase(upass)) {

				String delStatus = obj.getDelStatus();// 删除状态(F:未删除,T:假删除)
				Integer userStatus = obj.getUserStatus();//用户状态(-1:删除状态,0:停用,1:启用)

				if (Validator.isEmpty(userStatus)) {
					userStatus = 10000;//自定值,防止用户状态未设置
				}
				if (Validator.isEmpty(delStatus)) {
					delStatus = "E";//自定值,防止用户删除状态为设置
				}

				if (userStatus == 10000 || "E".equals(delStatus)) {
					result.setEntity("F");
					result.setMessage("用户状态异常,请联系系统管理员");
					return result;
				}

				if ("T".equals(delStatus) || userStatus == -1) {
					result.setEntity("F");
					result.setMessage("用户已留痕删除,请联系系统管理员");
					return result;
				}

				if (userStatus == 0) {
					result.setEntity("F");
					result.setMessage("用户已停用,请联系系统管理员");
					return result;
				}

				//虽然密码正确,但是需要判断下之前缓存中是否存在该用户的登陆错误信息,如果存在,则依然返回等待
				LonErrToken tokenE = (LonErrToken) SystemTools.getInstance().getCache("loginErrToken")
						.getCacheCloneByKey(addressIP + obj.getUserEname());
				if (!Validator.isEmpty(tokenE)) {
					String count = tokenE.getLoginCount();
					int c = Integer.parseInt(count);
					if ("3".equals(tokenE.getLoginCount()) || "6".equals(tokenE.getLoginCount())
							|| "9".equals(tokenE.getLoginCount()) || c > 12) {
						//如果错误次数等于以上几个参数,也同样需要校验下时间是否已经过期,防止时间已过,且登录密码正确,却一直没有更新缓存
						//setErrToken(vo, remoteIp, br, obj);
						LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
						result.setEntity("F");
						result.setMessage("账户已被锁定");
						return result;
					}
				}

				String randNum = PassportHelper.getInstance().createRandomString(12);
				Token token = new Token();
				String tokenId = com.apache.cache.util.Validator.generate() + randNum;
				token.setTokenId(tokenId);
				token.setUserEname(DesUtils.getInstance().encrypt(userEname));
				token.setUserCname(obj.getUserCname());
				token.setLoginTime(df.format(new Date()));
				token.setEmail(DesUtils.getInstance().encrypt(obj.getEmail()));
				token.setMobile(DesUtils.getInstance().encrypt(obj.getMobile()));
				token.setUserId(obj.getUserId());
				result.setEntity(token);
				result.setMessage("登录成功");
				LoginInfo loginInfo = new LoginInfo();
				loginInfo.setLgnLastipaddress(addressIP);
				loginInfo.setUserEname(userEname);
				token.setLoginInfo(loginInfo);

				SystemTools.getInstance().getCache("loginErrToken").removeCacheObject(addressIP + obj.getUserEname());
				String synFlag = SystemTools.getInstance().getValue("synFlag");
				if ("1".equals(synFlag)) {
					String tokenMapId = (String) SystemTools.getInstance().getCache("userEnaemForTokenId")
							.getCacheCloneByKey(token.getUserEname());
					if (!Validator.isNull(tokenMapId)) {
						SystemTools.getInstance().getCache("loginToken").removeCacheObject(tokenMapId);
					}
					SystemTools.getInstance().getCache("userEnaemForTokenId")
							.createCacheObject(token.getUserEname(), tokenId);
					//存储缓存
					SystemTools.getInstance().getCache("loginToken").createCacheObject(tokenId, token);
				} else {
					//存储缓存
					SystemTools.getInstance().getCache("loginToken").createCacheObject(tokenId, token);
				}
				return result;
			} else {
				result.setEntity("F");
//				result.setMessage("密码错误");
				result.setMessage("用户名或密码错误");
				LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
				return result;
			}
		} else {
			result.setEntity("F");
//			result.setMessage("用户不存在");
			result.setMessage("用户名或密码错误");
			LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
			return result;
		}
	}

	/**
	 * description:  根据ename查询用户信息
	 * @param vo
	 * @return  
	 * @author Hou Dayu 
	 * @update 2015年2月13日11:08:40 yxcui 增加手机号邮箱登陆
	 * 
	 */
	public Object getInfoByEname(String userEname) {
		if (Validator.isNull(userEname)) {
			return null;
		}
		String sql = uctUserDao.getSql(3);// from UctUser where userEname :=userEname

		String mobileLogin = SystemTools.getInstance().getValue("mobileLogin");
		String emailLogin = SystemTools.getInstance().getValue("emailLogin");

		if ("1".equals(mobileLogin)) {
			sql += "or mobile :=userEname ";
		}
		if ("1".equals(emailLogin)) {
			sql += "or email :=userEname ";
		}

		MethodParam param = new MethodParam("ByUserEname", "", sql, "com.apache.passport.entity.UctUser");
		param.setParams("userEname", userEname);
		if ("1".equals(mobileLogin)) {
			param.setParams("mobile", userEname);
		}
		if ("1".equals(emailLogin)) {
			param.setParams("email", userEname);
		}
		return uctUserDao.selectSingle(param);
	}

	/**
	 * description:  根据IP及用户名获取黑名单
	 * @param vo
	 * @return  
	 * @author Hou Dayu 
	 * @update 2014-12-24
	 */
	public Object getBrInfoByIp(ParamsVo<UctUser> vo) {
		String remoteIp = (String) vo.getParams("remoteIp");
		String userEname = (String) vo.getParams().get("userEname");
		//只验证用户名
		String sql = blackRosterDao.getSql(4);
		if (!Validator.isNull(remoteIp)) {
			sql += " and brIpaddress :=brIpaddress ";
		}
		MethodParam param = new MethodParam("ByIpOrUserEname", "", sql, BlackRoster.class.getName());
		param.setParams("brIpaddress", remoteIp);
		param.setParams("brAccount", userEname);
		return blackRosterDao.selectSingle(param);
	}

	public void setBlackRosterDao(IDao blackRosterDao) {
		this.blackRosterDao = blackRosterDao;
	}
}
